﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.ExtensibleStorage;
using Autodesk.Revit.UI;
using Autodesk.Revit.UI.Selection;
using YArchitech.LIB;
using YArchitech.Revit;

namespace YArchitech.MEP
{
	public class CreateProtectRange
	{
		public IList<Element> GeteElementByRectangle(Document doc, HyRangeCheckMajor rangeCheckApplicatScenarios)
		{
			IList<Element> result = null;
			if (rangeCheckApplicatScenarios == HyRangeCheckMajor.HyGPS)
			{
				result = this.GetGPSElementByRectangle(doc);
			}
			else if (rangeCheckApplicatScenarios == HyRangeCheckMajor.HyDQ)
			{
				result = this.GetDQElementByRectangle(doc);
			}
			return result;
		}

		public IList<Element> GetGPSElementByRectangle(Document doc)
		{
			Selection selection = new UIDocument(doc).Selection;
			return selection.PickElementsByRectangle(new CreateProtectRange.GPSMassSelectionFilter(), "请框选要添加检查范围的感应器消防设备…");
		}

		public IList<Element> GetDQElementByRectangle(Document doc)
		{
			Selection selection = new UIDocument(doc).Selection;
			return selection.PickElementsByRectangle(new CreateProtectRange.DQMassSelectionFilter(), "请框选要添加检查范围的感应器…");
		}

		public IList<Element> GetElementByView(Document doc, View view)
		{
			ElementCategoryFilter item = new ElementCategoryFilter(BuiltInCategory.OST_MechanicalEquipment);
			ElementCategoryFilter item2 = new ElementCategoryFilter(BuiltInCategory.OST_Sprinklers);
			ElementCategoryFilter item3 = new ElementCategoryFilter(BuiltInCategory.OST_FireAlarmDevices);
			IList<ElementFilter> list = new List<ElementFilter>
			{
				item,
				item2,
				item3
			};
			LogicalOrFilter logicalOrFilter = new LogicalOrFilter(list);
			return new FilteredElementCollector(doc, view.Id).WherePasses(logicalOrFilter).WhereElementIsNotElementType().ToElements();
		}

		public List<DetailCurve> CreatDetailCurve(Document doc, View view, IList<Element> collection, HyRangeCheckMajor rangeCheckApplicatScenarios)
		{
			Path.Combine(Product.WorkingLocation, "HYShared Parameters.txt");
			List<DetailCurve> list = new List<DetailCurve>();
			foreach (Element element in collection)
			{
				Element element2 = element;
				using (SubTransaction subTransaction = new SubTransaction(doc))
				{
					subTransaction.Start();
					this.DeleteTags(doc, element2);
					subTransaction.Commit();
				}
				double detailCurveRadius = this.GetDetailCurveRadius(element2, rangeCheckApplicatScenarios);
				if (detailCurveRadius >= 0.328)
				{
					DetailCurve detailCurve = this.CreateDetailCurve(doc, view, element2, detailCurveRadius);
					ElementId elementId = null;
					new DefinitionLineType(doc, element2, detailCurve, out elementId);
					using (SubTransaction subTransaction2 = new SubTransaction(doc))
					{
						subTransaction2.Start();
						detailCurve.get_Parameter(BuiltInParameter.BUILDING_CURVE_GSTYLE).Set(elementId);
						subTransaction2.Commit();
					}
					doc.Regenerate();
					this.RecordLastTimeTags(doc, element2, new List<Element>
					{
						detailCurve
					});
					list.Add(detailCurve);
				}
			}
			return list;
		}

		public List<DetailCurve> CreatActiveViewDetailCurve(Document doc, IList<Element> collection, HyRangeCheckMajor rangeCheckApplicatScenarios)
		{
			Path.Combine(Product.WorkingLocation, "HYShared Parameters.txt");
			List<DetailCurve> list = new List<DetailCurve>();
			foreach (Element element in collection)
			{
				Element element2 = element;
				using (SubTransaction subTransaction = new SubTransaction(doc))
				{
					subTransaction.Start();
					this.DeleteTags(doc, element2);
					subTransaction.Commit();
				}
				double detailCurveRadius = this.GetDetailCurveRadius(element2, rangeCheckApplicatScenarios);
				if (detailCurveRadius >= 0.328)
				{
					DetailCurve detailCurve = this.CreateActiveViewDetailCurve(doc, element2, detailCurveRadius);
					ElementId elementId = null;
                    new DefinitionLineType(doc, element2, detailCurve, out elementId);
					using (SubTransaction subTransaction2 = new SubTransaction(doc))
					{
						subTransaction2.Start();
						detailCurve.get_Parameter(BuiltInParameter.BUILDING_CURVE_GSTYLE).Set(elementId);
						subTransaction2.Commit();
					}
					doc.Regenerate();
					this.RecordLastTimeTags(doc, element2, new List<Element>
					{
						detailCurve
					});
					list.Add(detailCurve);
				}
			}
			return list;
		}

		public double GetDetailCurveRadius(Element elem, HyRangeCheckMajor rangeCheckApplicatScenarios)
		{
			double result = 0.0;
			if (rangeCheckApplicatScenarios == HyRangeCheckMajor.HyGPS)
			{
				if (this.IsParamExist(elem, "喷淋半径") && this.GetParameterByName(elem, "喷淋半径").HasValue)
				{
					result = this.GetParameterByName(elem, "喷淋半径").AsDouble();
				}
				else if (this.IsParamExist(elem, "保护半径") && this.GetParameterByName(elem, "保护半径").HasValue)
				{
					result = this.GetParameterByName(elem, "保护半径").AsDouble();
				}
			}
			else if (rangeCheckApplicatScenarios == HyRangeCheckMajor.HyDQ && this.IsParamExist(elem, "保护半径") && this.GetParameterByName(elem, "保护半径").HasValue)
			{
				result = this.GetParameterByName(elem, "保护半径").AsDouble() * 3.2808398950131235;
			}
			return result;
		}

		public void CreateSharedParames(Document doc, string sharedParamPath, Element elem, DetailCurve detailCurve)
		{
			SharedParameters sharedParameters = new SharedParameters();
			Category category = elem.Category;
			string text = "Hy_" + elem.Category.Name + "保护范围";
            ParameterType sharedParamsGroupType = (ParameterType)1;
			sharedParameters.DefineSharedParameters(new UIDocument(doc).Application, sharedParamPath, category, text, sharedParamsGroupType);
			IList<Parameter> parameters = elem.GetParameters(text);
			if (parameters.Count != 0)
			{
				parameters[0].Set(detailCurve.Id.ToString());
			}
		}

		public Parameter GetParameterByName(Element elem, string strParamName)
		{
			Parameter result = null;
			IList<Parameter> parameters = elem.GetParameters(strParamName);
			if (parameters.Count != 0)
			{
				result = parameters.ElementAt(0);
			}
			return result;
		}

		public bool IsParamExist(Element elem, string strParamName)
		{
			IList<Parameter> parameters = elem.GetParameters(strParamName);
			return parameters.Count != 0;
		}

		public DetailCurve CreateDetailCurve(Document doc, View view, Element elem, double radius)
		{
			DetailCurve result = null;
			Location location = elem.Location;
			if (location is LocationCurve)
			{
				LocationCurve locationCurve = location as LocationCurve;
				XYZ center = (locationCurve.Curve.GetEndPoint(0) + locationCurve.Curve.GetEndPoint(1)) / 2.0;
				using (SubTransaction subTransaction = new SubTransaction(doc))
				{
					subTransaction.Start();
					result = doc.CreatYJKDetailCurve(doc.CreatYJKArc(center, radius, 0.0, Math.PI*2, XYZ.BasisX, XYZ.BasisY));
					subTransaction.Commit();
					return result;
				}
			}
			if (location is LocationPoint)
			{
				LocationPoint locationPoint = location as LocationPoint;
				XYZ center = locationPoint.Point;
				using (SubTransaction subTransaction2 = new SubTransaction(doc))
				{
					subTransaction2.Start();
					result = doc.CreatYJKDetailCurve(doc.CreatYJKArc(center, radius, 0.0, Math.PI*2, XYZ.BasisX, XYZ.BasisY));
					subTransaction2.Commit();
				}
			}
			return result;
		}

		public DetailCurve CreateActiveViewDetailCurve(Document doc, Element elem, double radius)
		{
			DetailCurve result = null;
			Location location = elem.Location;
			if (location is LocationCurve)
			{
				LocationCurve locationCurve = location as LocationCurve;
				XYZ center = (locationCurve.Curve.GetEndPoint(0) + locationCurve.Curve.GetEndPoint(1)) / 2.0;
				using (SubTransaction subTransaction = new SubTransaction(doc))
				{
					subTransaction.Start();
					result = doc.CreatYJKDetailCurve(doc.CreatYJKArc(center, radius, 0.0, Math.PI*2, XYZ.BasisX, XYZ.BasisY));
					subTransaction.Commit();
					return result;
				}
			}
			if (location is LocationPoint)
			{
				LocationPoint locationPoint = location as LocationPoint;
				XYZ center = locationPoint.Point;
				using (SubTransaction subTransaction2 = new SubTransaction(doc))
				{
					subTransaction2.Start();
					result = doc.CreatYJKDetailCurve(doc.CreatYJKArc(center, radius, 0.0, Math.PI*2, XYZ.BasisX, XYZ.BasisY));
					subTransaction2.Commit();
				}
			}
			return result;
		}

		public void DeletOldDetailCurve(Document doc, View view, Element elem, DetailCurve detailCurve)
		{
			string strParamName = "Hy_" + elem.Category.Name + "保护范围";
			Parameter parameterByName = this.GetParameterByName(elem, strParamName);
			if (parameterByName.HasValue)
			{
				char[] separator = new char[]
				{
					','
				};
				string[] array = parameterByName.AsString().Split(separator, StringSplitOptions.RemoveEmptyEntries);
				foreach (string value in array)
				{
					ICollection<ElementId> collection = new FilteredElementCollector(doc, view.Id).OfClass(typeof(CurveElement)).ToElementIds();
					foreach (ElementId elementId in collection)
					{
						if (elementId.ToString().Equals(value))
						{
							using (SubTransaction subTransaction = new SubTransaction(doc))
							{
								subTransaction.Start();
								doc.Delete(elementId);
								subTransaction.Commit();
								break;
							}
						}
					}
				}
				Parameter parameterByName2 = this.GetParameterByName(elem, strParamName);
				string str = parameterByName2.AsString();
				parameterByName2.Set(str + "," + detailCurve.Id.ToString());
				return;
			}
			Parameter parameterByName3 = this.GetParameterByName(elem, strParamName);
			parameterByName3.Set(detailCurve.Id.ToString());
		}

		public void DeletActiveViewOldDetailCurve(Document doc, Element elem, DetailCurve detailCurve)
		{
			string strParamName = "Hy_" + elem.Category.Name + "保护范围";
			Parameter parameterByName = this.GetParameterByName(elem, strParamName);
			if (parameterByName.HasValue)
			{
				char[] separator = new char[]
				{
					','
				};
				string[] array = parameterByName.AsString().Split(separator, StringSplitOptions.RemoveEmptyEntries);
				foreach (string value in array)
				{
					ICollection<ElementId> collection = new FilteredElementCollector(doc, doc.ActiveView.Id).OfClass(typeof(CurveElement)).ToElementIds();
					foreach (ElementId elementId in collection)
					{
						if (elementId.ToString().Equals(value))
						{
							using (SubTransaction subTransaction = new SubTransaction(doc))
							{
								subTransaction.Start();
								doc.Delete(elementId);
								subTransaction.Commit();
								break;
							}
						}
					}
				}
				Parameter parameterByName2 = this.GetParameterByName(elem, strParamName);
				string str = parameterByName2.AsString();
				parameterByName2.Set(str + "," + detailCurve.Id.ToString());
				return;
			}
			Parameter parameterByName3 = this.GetParameterByName(elem, strParamName);
			parameterByName3.Set(detailCurve.Id.ToString());
		}

		public ViewFamilyType GetFloorPlanViewFamilyType(Document doc)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			filteredElementCollector.OfClass(typeof(ViewFamilyType));
            return filteredElementCollector.Cast<ViewFamilyType>().First((ViewFamilyType vft) => (int)vft.ViewFamily == 109);
		}

		public List<View> GetFloorPlanViews(Document doc)
		{
			ViewFamilyType floorPlanViewFamilyType = this.GetFloorPlanViewFamilyType(doc);
			List<View> list = new List<View>();
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(doc);
			IList<Element> list2 = filteredElementCollector.OfClass(typeof(View)).ToElements();
			if (list2 != null)
			{
				foreach (Element element in list2)
				{
					View view = element as View;
					if (view.GetTypeId() == floorPlanViewFamilyType.Id)
					{
						list.Add(view);
					}
				}
			}
			return list;
		}

		public void RecordLastTimeTags(Document doc, Element elem, List<Element> newgrpElements)
		{
			StringBuilder stringBuilder = new StringBuilder();
			foreach (Element element in newgrpElements)
			{
				stringBuilder.Append("@" + element.Id.IntegerValue.ToString());
			}
			Guid guid = new Guid("C0C7C53C-8A31-4562-88A0-293290913CA8");
			Schema schema;
			if (Schema.Lookup(guid) == null)
			{
				SchemaBuilder schemaBuilder = new SchemaBuilder(guid);
				schemaBuilder.SetReadAccessLevel((AccessLevel)1);
				schemaBuilder.SetWriteAccessLevel((AccessLevel)1);
				schemaBuilder.SetSchemaName("RecordTagElems");
				schemaBuilder.SetDocumentation("Data store for Tags info in a water pit");
				schemaBuilder.AddSimpleField("RecordTagElems", typeof(string));
				schema = schemaBuilder.Finish();
			}
			else
			{
				schema = Schema.Lookup(guid);
			}
			Entity entity = new Entity(schema);
			schema.GetField("RecordTagElems");
			entity.Set<string>("RecordTagElems", stringBuilder.ToString());
			if (elem.Document.IsLinked)
			{
				doc.ActiveView.SetEntity(entity);
				return;
			}
			elem.SetEntity(entity);
		}

		public void DeleteTags(Document doc, Element element)
		{
			Guid guid = new Guid("C0C7C53C-8A31-4562-88A0-293290913CA8");
			if (Schema.Lookup(guid) == null)
			{
				return;
			}
			Entity entity = element.GetEntity(Schema.Lookup(guid));
			if (entity.Schema == null)
			{
				return;
			}
			string text = entity.Get<string>(Schema.Lookup(guid).GetField("RecordTagElems"));
			if (string.IsNullOrEmpty(text))
			{
				return;
			}
			char[] separator = new char[]
			{
				'@'
			};
			string[] array = text.Split(separator, StringSplitOptions.RemoveEmptyEntries);
			foreach (string s in array)
			{
				int num;
				if (int.TryParse(s, out num))
				{
					ElementId elementId = new ElementId(num);
					Element element2 = doc.GetElement(elementId);
					if (element2 != null)
					{
						doc.DeleteElement(element2);
					}
				}
			}
		}

		public class GPSMassSelectionFilter : ISelectionFilter
		{
			public bool AllowElement(Element elem)
			{
				return elem.Category.Id.IntegerValue == -2001140 || elem.Category.Id.IntegerValue == -2008099;
			}

			public bool AllowReference(Reference reference, XYZ position)
			{
				throw new NotImplementedException();
			}
		}

		public class DQMassSelectionFilter : ISelectionFilter
		{
			public bool AllowElement(Element elem)
			{
				return elem.Category.Id.IntegerValue == -2008085;
			}

			public bool AllowReference(Reference reference, XYZ position)
			{
				throw new NotImplementedException();
			}
		}
	}
}
